package manage.commons.interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import manage.commons.Constants;
import manage.commons.annontations.AccessControl;
import manage.commons.annontations.AccessVerify;
import manage.commons.annontations.RequiredLogin;
import manage.commons.cookie.UserState;
import manage.commons.cookie.UserStateSessionManager;
import manage.commons.utils.AnnontationUtils;
import manage.commons.utils.CookieUtils;
import manage.modules.rbac.service.RBACService;
import manage.modules.worker.model.Worker;
import manage.modules.worker.model.WorkerInfo;
import manage.modules.worker.service.WorkerService;
import manage.modules.worker.util.WorkerLoginUtil;

import org.apache.struts2.StrutsStatics;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/**
 * 
 * @description:安全拦截器，检查是否登陆，相关权限
 * @author dongji
 * @since 2012-8-22 下午05:46:58
 */
public class SecurityInterceptor extends AbstractInterceptor {

	private static final long serialVersionUID = -4345830943640721739L;
	private WorkerService workerService;
	private RBACService rbacService;

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		final ActionContext context = invocation.getInvocationContext();
		final ActionProxy proxy = invocation.getProxy();
		final Object action = invocation.getAction();
		final HttpServletRequest request = (HttpServletRequest) context
				.get(StrutsStatics.HTTP_REQUEST);
		final HttpServletResponse response = (HttpServletResponse) context
				.get(StrutsStatics.HTTP_RESPONSE);
		String cookieUser = CookieUtils.getCookie(request, Constants.COOKIE_U);
		final UserStateSessionManager sessionManager = new UserStateSessionManager(
				cookieUser);
		Long currentWorkerId = null;
		UserState session = sessionManager.getUserState();
		if (null != session) {
			Worker sessionWorker = workerService.select(session.getUserId()
					.longValue());
			UserState dbUser = new UserState();
			dbUser.setUserId(sessionWorker.getWorkerId().intValue());
			dbUser.setPassword(sessionWorker.getPassword());
			boolean online = sessionManager.online(dbUser);
			if (online) {
				currentWorkerId = session.getUserId().longValue();
			}
		}
		final RequiredLogin require = AnnontationUtils.getFromMethedOrType(
				RequiredLogin.class, action, proxy.getMethod());
		if (require != null && require.value() == RequiredLogin.Required.FALSE) {
			// 不用登陆
		} else if ((require != null && require.value() == RequiredLogin.Required.TRUE)
				&& currentWorkerId == null || currentWorkerId == 0) {
			// 需要登录但没有登录就跳到登录页面
			if (request.getMethod().equalsIgnoreCase("post")) {
				String referer = request.getHeader("referer");
				request.setAttribute("forward", referer);
			} else {
				request.setAttribute("forward",
						WorkerLoginUtil.forword(request));
			}
			if (action instanceof ActionSupport) {
				((ActionSupport) action)
						.addActionError("您还没有登录，或是已经登录超时，请登录后继续操作。");
			}
			CookieUtils.removeCookie(response, Constants.COOKIE_U);
			return ActionSupport.LOGIN;
		}
		if (currentWorkerId != null) {
			// 登录后,获取并注入当前Worker
			if (action instanceof CurrentWorkerAware) {
				if (workerService.exists(currentWorkerId)) {
					WorkerInfo currentWorker = workerService
							.selectWorkerInfo(currentWorkerId);
					CurrentWorkerAware aware = (CurrentWorkerAware) action;
					aware.setCurrentWorker(currentWorker);
				} else {
					((ActionSupport) action).addActionError("员工ID="
							+ currentWorkerId + "不存在。");
					CookieUtils.removeCookie(response, Constants.COOKIE_U);
					return ActionSupport.ERROR;
				}
			}
			// 验证访问路径权限
			final AccessVerify accessVerify = AnnontationUtils
					.getFromMethedOrType(AccessVerify.class, action,
							proxy.getMethod());
			if (null != accessVerify && accessVerify.value() > 0) {
				boolean hasUri = rbacService.hasPermissions(
						request.getRequestURI(), currentWorkerId);
				if (!hasUri) {
					// response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
					return Constants.UN_AUTHOR;
				}
			}
			final AccessControl needAccessRbac = AnnontationUtils
					.getFromMethedOrType(AccessControl.class, action,
							proxy.getMethod());
			if (needAccessRbac != null) {
				request.setAttribute(Constants.RBAC,
						rbacService.listRBACByWorkerId(currentWorkerId));
			}
		}
		return invocation.invoke();
	}

	public void setWorkerService(WorkerService workerService) {
		this.workerService = workerService;
	}

	public void setRbacService(RBACService rbacService) {
		this.rbacService = rbacService;
	}

}
